package models

import (
	"ShopSupplierApi/models/mysql"
	"ShopSupplierApi/utils"
	dbsql "database/sql"
	"strconv"
	"strings"
)

//Region 区域信息
type Region struct {
	Children map[string]*Region //下属地区信息
	ID       int                //地区ID
	Name     string             //地区名称
}

//ExpressRegion 快递地区费用
type ExpressRegion struct {
	RegionID   int     //地区ID
	DlyID      int     //快递ID
	SupplierID uint64  //供应商ID
	FirstCost  float64 //首重费用
	ExtCost    float64 //续重费用
}

//Express 快递
type Express struct {
	Regions     []ExpressRegion //地区配置信息
	ID          int             //快递ID
	Name        string          //快递名称
	HasCod      string          //货到付款("true","false")
	FirstUnit   int             //首重
	extUnit     int             //续重
	Protect     string          //保价("true","flase")
	ProtectRate float64         //保价费率
	MinProtect  float64         //最低保价金额
	Setting     string          //地区费用类型("0"=>统一设置,"1"=>分地区单独设置)
	DefaultArea string          //未设置的地区是否按默认费用计算("true","false")
	FirstCost   float64         //首重费用
	ExtCost     float64         //续重费用
	CorpID      int             //物流公司ID
	SupplierID  uint64          //供应商ID
	OrderNum    int             //排序
	Status      string          //是否前台显示('0','1')
}

//创建地区信息
func createRegion() *Region {
	result := &Region{}
	result.Children = make(map[string]*Region, 0)
	return result
}

//ExpressCorpList 物流公司列表
//param p *Page 数据分页信息
func ExpressCorpList(p *Page) []map[string]interface{} {
	sql := "SELECT corp_id,corp_code,name,website,request_url,ordernum FROM sdb_b2c_dlycorp WHERE disabled = \"false\" "
	rows, err := mysql.Rows(p.SQL(sql))
	if err != nil {
		return make([]map[string]interface{}, 0)
	}
	for _, v := range rows { //转换先关的值
		v["corp_id"], _ = mysql.Int(v["corp_id"])
		v["corp_code"], _ = mysql.String(v["corp_code"])
		v["name"], _ = mysql.String(v["name"])
		v["website"], _ = mysql.String(v["website"])
		v["request_url"], _ = mysql.String(v["request_url"])
		v["ordernum"], _ = mysql.Int(v["ordernum"])
	}
	p.Rows = int64(len(rows))
	p.CountRows(sql)
	return rows
}

//AddExpressCorp 新增物流公司
//param name string 物流公司名称
//param corpCode string 物理公式代码
//param website string 物流公司官网
//param requestURL string 快递查询网址
//param orderNum uint 排序
func AddExpressCorp(name string, corpCode string, website string, requestURL string, orderNum uint) bool {
	sql := "INSERT INTO sdb_b2c_dlycorp(corp_code,name,ordernum,website,request_url)VALUES(" +
		" ?,?,?,?,? )"
	_, err := mysql.Exec(sql, corpCode, name, orderNum, website, requestURL)
	return err == nil
}

//UpdateExpressCorp 编辑物流公司
//param corpID uint 物流公司ID
//param name string 物流公司名称
//param corpCode string 物理公式代码
//param website string 物流公司官网
//param requestURL string 快递查询网址
//param orderNum uint 排序
func UpdateExpressCorp(corpID uint, name string, corpCode string, website string, requestURL string, orderNum uint) bool {
	sql := "UPDATE sdb_b2c_dlycorp SET corp_code=?,name=?,ordernum=?," +
		"website=?,request_url=? WHERE corp_id = ? "
	result, err := mysql.Exec(sql, corpCode, name, orderNum, website, requestURL, corpID)
	if err != nil {
		return false
	}
	r, err := result.RowsAffected()
	if err != nil {
		return false
	}
	return r > 0
}

//ExpressList 快递列表
//param supplierID uint64 供应商ID
//param p *Page 数据分页信息
func ExpressList(supplierID uint64, p *Page) []map[string]interface{} {
	sql := "SELECT has_cod,dt_id,dt_name,protect,dt_status,ordernum FROM sdb_b2c_dlytype WHERE supplier_id = ? ORDER BY ordernum ASC "
	rows, err := mysql.Rows(p.SQL(sql), supplierID)
	if err != nil || len(rows) < 1 {
		return make([]map[string]interface{}, 0)
	}
	for _, v := range rows {
		v["has_cod"], _ = mysql.String(v["has_cod"])
		v["dt_id"], _ = mysql.Int64(v["dt_id"])
		v["dt_name"], _ = mysql.String(v["dt_name"])
		v["protect"], _ = mysql.String(v["protect"])
		v["dt_status"], _ = mysql.String(v["dt_status"])
		v["ordernum"], _ = mysql.Int(v["ordernum"])
	}
	p.Rows = int64(len(rows))
	p.CountRows(sql, supplierID)
	return rows
}

//RegionInfo 地区信息
func RegionInfo() map[string]*Region {
	result := make(map[string]*Region, 0)
	sql := "SELECT region_id,local_name,region_path FROM sdb_ectools_regions ORDER BY region_id ASC "
	rows, err := mysql.Rows(sql)
	if err != nil {
		return result
	}
	for _, v := range rows {
		rg := createRegion()
		rg.ID, _ = mysql.Int(v["region_id"])
		rg.Name, _ = mysql.String(v["local_name"])
		regionPath, _ := mysql.String(v["region_path"])
		ids := strings.Split(strings.Trim(regionPath, ","), ",")
		switch len(ids) {
		case 1: //省级
			if vv, ok := result[strconv.Itoa(rg.ID)]; ok { //存在更新集合中的信息
				vv.ID = rg.ID
				vv.Name = rg.Name
			} else { //不存在则新增到集合中
				result[strconv.Itoa(rg.ID)] = rg
			}
		case 2: //市级
			pid, err := strconv.Atoi(ids[0])
			if err != nil { //转换错误,直接跳出
				continue
			}
			if _, ok := result[strconv.Itoa(pid)]; !ok {
				result[strconv.Itoa(pid)] = createRegion()
			}
			t := result[strconv.Itoa(pid)].Children
			if vv, ok := t[strconv.Itoa(rg.ID)]; ok { //如果该地区已存在,更新地区信息
				vv.ID = rg.ID
				vv.Name = rg.Name
			} else { //该地区不存在,添加
				t[strconv.Itoa(rg.ID)] = rg
			}
		case 3: //县级
			pid, err := strconv.Atoi(ids[0])
			if err != nil { //转换错误,直接跳出
				continue
			}
			cid, err := strconv.Atoi(ids[1])
			if err != nil { //转换错误,直接跳出
				continue
			}
			if _, ok := result[strconv.Itoa(pid)]; !ok { //检测省级信息是否存在.不存在添加
				result[strconv.Itoa(pid)] = createRegion()
			}
			if _, ok := result[strconv.Itoa(pid)].Children[strconv.Itoa(cid)]; !ok { //检测市级信息是否存在.不存在添加
				result[strconv.Itoa(pid)].Children[strconv.Itoa(cid)] = createRegion()
			}
			result[strconv.Itoa(pid)].Children[strconv.Itoa(cid)].Children[strconv.Itoa(rg.ID)] = rg //增加县级信息
		}
	}
	return result
}

//AddExpress 增加快递信息
//param e *Express 快递信息
func AddExpress(e *Express) bool {
	dlytype := "INSERT INTO sdb_b2c_dlytype" +
		"(dt_name,has_cod,firstunit,continueunit,protect,protect_rate,minprice,setting,def_area_fee,firstprice,continueprice,corp_id,dt_status,ordernum,supplier_id)" +
		"VALUES(?,?,?,??,?,?,?,?,?,?,?,?,?,?)"
	err := mysql.Transaction(func(tx *dbsql.Tx) error {
		result, err := tx.Exec(dlytype, e.Name, e.HasCod, e.FirstUnit, e.extUnit, e.Protect, e.ProtectRate, e.MinProtect, e.Setting, e.DefaultArea, e.FirstCost, e.ExtCost, e.CorpID, e.Status, e.OrderNum, e.SupplierID)
		if err != nil {
			utils.Logger.Error("数据插入失败",dlytype,err)
			return err
		}
		newID, err := result.LastInsertId()
		if err != nil {
			utils.Logger.Error("插入记录ID获取失败",err)
			return err
		}
		if e.Regions != nil && len(e.Regions) > 0 {
			regionSQL := "INSERT INTO lcf_dlcost(dltype_id,supplier_id,region_id,first_cost,extend_cost)VALUES " +
				"(?,?,?,?,?)"
			return func() error { //匿名函数确保预处理stmt能正确关闭
				stmt, err := mysql.Db.Prepare(regionSQL)
				defer func() {
					stmt.Close()
				}()
				if err != nil {
					return err
				}
				stmt = tx.Stmt(stmt)
				for _, rg := range e.Regions {
					_, err := stmt.Exec(rg.DlyID, e.SupplierID, newID, rg.FirstCost, rg.ExtCost)
					if err != nil {
						return err
					}
				}
				return nil
			}()
		}
		return nil
	})
	if err != nil {
		utils.Logger.Error(err.Error())
		return false
	}
	return true
}
